/**
 * @author hhlxy
 * @version 1.0
 * @since 2025/8/5
 * 文章控制器类，负责处理与文章相关的HTTP请求，包括文章的增删改查、点赞等操作
 */
package cn.yilongquan.controller;


import cn.yilongquan.authorize.PreAuthorize;
import cn.yilongquan.service.ArticleService;
import cn.yilongquan.user.domain.Article;
import cn.yilongquan.user.query.ArticleQuery;
import cn.yilongquan.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 文章控制器，提供文章的增删改查、相关文章查询及点赞/取消点赞等接口
 */
@Api(value = "article相关的接口", tags = "文章管理")
@RestController
@RequestMapping("/article")
public class ArticleController {

    @Autowired
    private ArticleService articleService;



    // 新增：浏览量统计接口点赞
    @PostMapping("/countView/{id}")
    public R countView(@PathVariable Long id) {
        // 调用服务层更新浏览量
        int newReadCount = articleService.increaseReadCount(id);
        return R.ok(newReadCount);
    }
    /**
     * 根据ID查询指定文章信息
     * @param id 文章ID
     * @return 文章详情信息
     */
    @ApiOperation(value = "查询指定文章信息")
    @GetMapping("/{id}")
    @PreAuthorize(sn = "article:findById", name = "根据ID查询文章", descs = "根据ID查询指定文章的详细信息")
    public R findById(@PathVariable("id") Long id) {
        return R.ok(articleService.findById(id));
    }

    /**
     * 查询所有文章信息
     * @return 文章列表
     */
    @ApiOperation(value = "查询所有文章信息")
    @GetMapping
    @PreAuthorize(sn = "article:findAll", name = "查询所有文章", descs = "查询系统中所有的文章信息")
    public R findAll(){
        return R.ok(articleService.findAll());
    }

    /**
     * 根据ID删除指定文章
     * @param id 文章ID
     * @return 操作结果
     */
    @ApiOperation(value = "删除指定文章信息")
    @DeleteMapping("/{id}")
    @PreAuthorize(sn = "article:deleteById", name = "根据ID删除文章", descs = "根据ID删除指定的文章")
    public R deletebyId(@PathVariable("id")Long id){
        articleService.deleteById(id);
        return R.ok();
    }

    /**
     * 批量删除文章
     * @param ids 文章ID列表
     * @return 操作结果
     */
    @ApiOperation(value = "批量删除文章信息")
    @PostMapping("/deleteAll")
    @PreAuthorize(sn = "article:batchDelete", name = "批量删除文章", descs = "根据ID列表批量删除文章")
    public R batchDelete(@RequestBody List<Long> ids){
        articleService.batchDelete(ids);
        return R.ok();
    }


    /**
     * 添加或修改文章
     * @param article 文章对象
     * @return 操作结果
     * 说明：当ID为空时执行新增操作；当ID不为空时执行更新操作
     */
    @ApiOperation(value = "添加或修改文章信息")
    @PostMapping("/add")
    @PreAuthorize(sn = "article:addOrUpdate", name = "添加或修改文章", descs = "新增文章或更新已有文章信息")
    public R add(@RequestBody Article article){
        if(article.getId() == null){
            articleService.add(article);
        }else {
            articleService.update(article);
        }
        return R.ok();
    }

    /**
     * 分页查询文章信息
     * @param articleQuery 文章查询对象，包含分页参数和查询条件
     * @return 分页查询结果
     */
    @ApiOperation(value = "分页查询文章信息")
    @PostMapping("/list")
    @PreAuthorize(sn = "article:pageList", name = "分页查询文章", descs = "根据查询条件分页查询文章信息")
    public R pageList(@RequestBody ArticleQuery articleQuery){
        return R.ok(articleService.pageList(articleQuery));
    }

    /**
     * 查询相关文章
     * @param articleType 文章类型ID（可选）
     * @param currentId 当前文章ID（必填）
     * @return 相关文章列表
     */
    @ApiOperation(value = "查询相关文章")
    @GetMapping("/related")
    @PreAuthorize(sn = "article:getRelated", name = "查询相关文章", descs = "根据文章类型和当前文章ID查询相关文章")
    public R getRelatedArticles(
            @RequestParam(value = "articleType", required = false) Long articleType,
            @RequestParam("currentId") Long currentId) {

        if (currentId == null) {
            return R.fail("currentId不能为空");
        }

        List<Article> relatedArticles = articleService.findRelatedByType(articleType, currentId);
        return R.ok(relatedArticles);
    }

    /**
     * 文章点赞（点赞数+1）
     * @param articleId 文章ID
     * @return 点赞后的点赞数
     */
    @ApiOperation(value = "文章点赞")
    @PostMapping("/star/{articleId}")
    @PreAuthorize(sn = "article:star", name = "文章点赞", descs = "对指定文章进行点赞操作，点赞数+1")

    public R starArticle(
            @PathVariable Long articleId,
            HttpServletRequest request // 新增：通过request获取用户IP
    ) {
        // 1. 获取用户真实IP（处理代理情况）
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 多IP情况取第一个
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }

        // 2. 参数校验（现在IP由后端获取，不需要前端传了）
        if (articleId == null) {
            return R.fail("文章ID不能为空");
        }
        if (ip == null || ip.trim().isEmpty()) {
            return R.fail("无法获取IP地址");
        }

        // 3. 检查文章是否存在
        Article article = articleService.findById(articleId);
        if (article == null) {
            return R.fail("文章不存在");
        }

        // 4. 调用Service处理点赞逻辑（校验IP+更新点赞数+记录IP）
        boolean success = articleService.starArticle(articleId, ip.trim());
        if (success) {
            int newStarNum = articleService.getStarNum(articleId);
            return R.ok("starNum", newStarNum);
        } else {
            return R.fail("该IP已对文章点赞，无法重复操作");
        }
    }

    /**
     * 文章取消点赞（点赞数-1，最小为0）
     * @param articleId 文章ID
     * @return 取消点赞后的点赞数
     */
    @ApiOperation(value = "文章取消点赞")
    @PostMapping("/unstar/{articleId}")
    @PreAuthorize(sn = "article:unstar", name = "取消文章点赞", descs = "取消对指定文章的点赞，点赞数-1（不小于0）")
    public R unstarArticle(@PathVariable Long articleId,
                           HttpServletRequest request) {
        // 1. 获取用户IP（与点赞时的IP获取逻辑完全一致）
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 多IP情况取第一个
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }

        // 2. 参数校验
        if (articleId == null) {
            return R.fail("文章ID不能为空");
        }
        if (ip == null || ip.trim().isEmpty()) {
            return R.fail("无法获取IP地址");
        }


        // 3. 调用Service执行取消点赞（包含删除IP记录和更新点赞数）
        int newStarNum = articleService.unstarArticle(articleId, ip.trim());
        return R.ok("starNum", newStarNum);
    }

    /**
     * 获取点赞数前六的文章
     * @return 包含文章名称和点赞数的列表，适合ECharts渲染
     */
    @ApiOperation(value = "获取点赞数前六的文章", notes = "返回点赞数最多的前六篇文章，包含文章名称和点赞数")
    @GetMapping("/top6")
    @PreAuthorize(sn = "article:top6", name = "查询点赞数前六的文章", descs = "查询系统中点赞数排名前六的文章")
    public R getTop6LikedArticles() {
        List<Article> topArticles = articleService.findTop6ByStarNum();

        // 转换为前端ECharts需要的格式（只保留必要字段）
        List<Map<String, Object>> result = topArticles.stream()
                .map(article -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("articleName", article.getArticleName()); // X轴：文章名称
                    map.put("starNum", article.getArticleStarNum()); // Y轴：点赞数
                    return map;
                })
                .collect(Collectors.toList());

        return R.ok(result);
    }

    @GetMapping("/top5TagCount")
    @PreAuthorize(sn = "article:top5TagCount", name = "查询同类数量前五的文章", descs = "查查询同类数量前五的文章")

    public R getTop5TagCount() {
        System.out.println("进入查询");
        List<Map<String, Object>> tagCountList = articleService.findTop5TagCount();
        System.out.println("进入查询"+tagCountList);

        return R.ok(tagCountList);

    }
}
